#include "RedisMgr.h"

#include <cstring>
#include "ConfigMgr.h"
#include "const.h"
RedisMgr::~RedisMgr()
{

    std::cout<<"RedisMgr::~RedisMgr()"<<std::endl;
}

bool RedisMgr::Get(const std::string &key, std::string& value)
{

    //从连接池获取连接
    this->connect_ = pool_->GetConnection();
    if(this->connect_==nullptr)
    {
        std::cout << "get redis connection failed" << std::endl;
        return false;
    }

    //利用RAII思想，在函数结束时自动释放连接
    Defer defer([this](){pool_->ReturnConnection(this->connect_); connect_=nullptr;});

    this->reply_ = (redisReply*)redisCommand(this->connect_, "GET %s", key.c_str());
    if (reply_==NULL)
    {
        std::cout << "[ GET  " << key << " ] failed" << std::endl;
        
        return false;
    }

    if(reply_->type!=REDIS_REPLY_STRING)
    {
        std::cout << "[ GET  " << key << " ] failed, type not string" << std::endl;
        freeReplyObject(this->reply_);
        return false;
    }
    value = reply_->str;
    freeReplyObject(reply_);
    return true;
    
}
bool RedisMgr::Set(const std::string &key, const std::string &value)
{

     //从连接池获取连接
    this->connect_ = pool_->GetConnection();
    if(this->connect_==nullptr)
    {
        std::cout << "get redis connection failed" << std::endl;
        return false;
    }

    //利用RAII思想，在函数结束时自动释放连接
    Defer defer([this](){pool_->ReturnConnection(this->connect_); connect_=nullptr;});



    reply_ = (redisReply*)redisCommand(connect_,"SET %s %s",key.c_str(),value.c_str());
    if(reply_==NULL)
    {
        std::cout<<"[SET  "<<key<<" ] failed"<<std::endl;
        
        return false;
    }
    if (reply_->type!=REDIS_REPLY_STATUS)
    {
        std::cout << "[ SET  " << key << " ] failed, type not status" << std::endl;
        freeReplyObject(this->reply_);
        return false;
    }
    std::cout<<"[SET  "<<key<<" "<<value<<" ] success"<<std::endl;
    freeReplyObject(this->reply_);
    return true;
    
}


bool RedisMgr::LPush(const std::string &key, const std::string &value)
{

    //从连接池获取连接
    this->connect_ = pool_->GetConnection();
    if(this->connect_==nullptr)
    {
        std::cout << "get redis connection failed" << std::endl;
        return false;
    }

    //利用RAII思想，在函数结束时自动释放连接
    Defer defer([this](){pool_->ReturnConnection(this->connect_); connect_=nullptr;});



    reply_= (redisReply*)redisCommand(connect_,"LPUSH %s %s",key.c_str(),value.c_str());
    if(reply_==NULL)
    {
        std::cout<<"[LPUSH  "<<key<<" "<<value<<" ] failed"<<std::endl;
        
        return false;
    }

    if (this->reply_->type != REDIS_REPLY_INTEGER || this->reply_->integer <= 0) {
        std::cout << "Execute command [ LPUSH " << key << "  " << value << " ] failure ! " << std::endl;
        freeReplyObject(this->reply_);
        return false;
    }
    std::cout << "Execute command [ LPUSH " << key << "  " << value << " ] success, return value : " << this->reply_->integer << std::endl;
    freeReplyObject(this->reply_);
    return true;

}
bool RedisMgr::LPop(const std::string &key, std::string& value)
{


    //从连接池获取连接
    this->connect_ = pool_->GetConnection();
    if(this->connect_==nullptr)
    {
        std::cout << "get redis connection failed" << std::endl;
        return false;
    }

    //利用RAII思想，在函数结束时自动释放连接
    Defer defer([this](){pool_->ReturnConnection(this->connect_); connect_=nullptr;});




    reply_ = (redisReply*)redisCommand(connect_,"LPOP %s",key.c_str());
    if(reply_==NULL||reply_->type ==REDIS_REPLY_NIL)
    {
        std::cout<<"[LPOP  "<<key<<" ] failed"<<std::endl;
        if(reply_)
        {
            freeReplyObject(this->reply_);
            
        }
        return false;
    }
   
    value = this->reply_->str;
    std::cout << "Execute command [ LPOP " << key << " ] success, return value : " << value << std::endl;
    freeReplyObject(this->reply_);
    return true;
}
bool RedisMgr::RPush(const std::string& key, const std::string& value)
{

    //从连接池获取连接
    this->connect_ = pool_->GetConnection();
    if(this->connect_==nullptr)
    {
        std::cout << "get redis connection failed" << std::endl;
        return false;
    }

    //利用RAII思想，在函数结束时自动释放连接
    Defer defer([this](){pool_->ReturnConnection(this->connect_); connect_=nullptr;});




    reply_ = (redisReply*)redisCommand(connect_,"RPUSH %s %s",key.c_str(),value.c_str());
    if(reply_==NULL||reply_->type != REDIS_REPLY_INTEGER)
    {
        std::cout << "Execute command [ RPUSH " << key << "  " << value << " ] failure ! " << std::endl;
        if (reply_)
        {
            
            freeReplyObject(this->reply_);
        }
        
        return false;
    }
    std::cout << "Execute command [ RPUSH " << key << "  " << value << " ] success, return value : " << this->reply_->integer << std::endl;
    freeReplyObject(this->reply_);
    return true;
}
bool RedisMgr::RPop(const std::string& key, std::string& value)
{

    //从连接池获取连接
    this->connect_ = pool_->GetConnection();
    if(this->connect_==nullptr)
    {
        std::cout << "get redis connection failed" << std::endl;
        return false;
    }

    //利用RAII思想，在函数结束时自动释放连接
    Defer defer([this](){pool_->ReturnConnection(this->connect_); connect_=nullptr;});




    reply_ = (redisReply*)redisCommand(connect_,"RPOP %s",key.c_str());
    if(reply_==NULL||reply_->type ==REDIS_REPLY_NIL)
    {
        std::cout<<"[RPOP  "<<key<<" ] failed"<<std::endl;
        freeReplyObject(this->reply_);
        return false;
    }
   
    value = this->reply_->str;
    std::cout << "Execute command [ RPOP " << key << " ] success, return value : " << value << std::endl;
    freeReplyObject(this->reply_);
    return true;
}
bool RedisMgr::HSet(const std::string &key, const std::string  &hkey, const std::string &value)
{   
    //从连接池获取连接
    this->connect_ = pool_->GetConnection();
    if(this->connect_==nullptr)
    {
        std::cout << "get redis connection failed" << std::endl;
        return false;
    }

    //利用RAII思想，在函数结束时自动释放连接
    Defer defer([this](){pool_->ReturnConnection(this->connect_); connect_=nullptr;});



    reply_ = (redisReply*)redisCommand(connect_,"HSET %s %s %s",key.c_str(),hkey.c_str(),value.c_str());
    if (reply_==NULL||reply_->type != REDIS_REPLY_INTEGER)
    {
        std::cout << "Execute command [ HSET " << key << "  " << hkey << "  " << value << " ] failure ! " << std::endl;
        if (reply_)
        {
            freeReplyObject(this->reply_);
        }
        
        return false;
    }
    
    freeReplyObject(this->reply_);
    return true;
}
bool RedisMgr::HSet(const char* key, const char* hkey, const char* hvalue, size_t hvaluelen)
{
    const char * argv[4];
    std::size_t argvlen[4];
    argv[0] = "HSET";
    argvlen[0] = strlen(argv[0]);
    argv[1] = key;
    argvlen[1] = strlen(key);
    argv[2] = hkey;
    argvlen[2] = strlen(hkey);
    argv[3] = hvalue;
    argvlen[3] = hvaluelen;

    //从连接池获取连接
    this->connect_ = pool_->GetConnection();
    if(this->connect_==nullptr)
    {
        std::cout << "get redis connection failed" << std::endl;
        return false;
    }

    //利用RAII思想，在函数结束时自动释放连接
    Defer defer([this](){pool_->ReturnConnection(this->connect_); connect_=nullptr;});



    reply_ = (redisReply*)redisCommandArgv(connect_, 4, argv, argvlen);
    if(reply_==NULL||reply_->type !=REDIS_REPLY_INTEGER)
    {
        std::cout << "Execute command [ HSET " << key << "  " << hkey << "  " << hvalue << " ] failure ! " << std::endl;
        if (reply_)
        {
            freeReplyObject(this->reply_);
        }
        
        return false;
    }
    std::cout << "Execute command [ HSET " << key << "  " << hkey << "  " << hvalue << " ] success, return value : " << this->reply_->integer << std::endl;
    freeReplyObject(this->reply_);
    return true;
}
std::string RedisMgr::HGet(const std::string &key, const std::string &hkey)
{
    //从连接池获取连接
    this->connect_ = pool_->GetConnection();
    if(this->connect_==nullptr)
    {
        std::cout << "get redis connection failed" << std::endl;
        return "";
    }

    //利用RAII思想，在函数结束时自动释放连接
    Defer defer([this](){pool_->ReturnConnection(this->connect_); connect_=nullptr;});



    reply_ = (redisReply*)redisCommand(connect_,"HGET %s %s",key.c_str(),hkey.c_str());
    if(reply_==NULL||reply_->type==REDIS_REPLY_NIL)
    {
        std::cout<<"[HGET  "<<key<<" "<<hkey<<" ] failed"<<std::endl;
        if (reply_)
        {
            freeReplyObject(reply_);
        }
        
        return "";
    }

    std::string value = this->reply_->str;
    std::cout << "Execute command [ HGET " << key << "  " << hkey << " ] success, return value : " << value << std::endl;
    freeReplyObject(this->reply_);
    return value;
}
bool RedisMgr::Del(const std::string &key)
{

    //从连接池获取连接
    this->connect_ = pool_->GetConnection();
    if(this->connect_==nullptr)
    {
        std::cout << "get redis connection failed" << std::endl;
        return false;
    }

    //利用RAII思想，在函数结束时自动释放连接
    Defer defer([this](){pool_->ReturnConnection(this->connect_); connect_=nullptr;});




    reply_ = (redisReply*)redisCommand(connect_,"DEL %s",key.c_str());
    if(reply_==NULL||reply_->type!=REDIS_REPLY_INTEGER)
    {
        std::cout<<"[DEL  "<<key<<" ] failed"<<std::endl;
        if (reply_)
        {
            freeReplyObject(reply_);
        }
        
        return false;
    }
    std::cout << "Execute command [ DEL " << key << " ] success, return value : " << this->reply_->integer << std::endl;
    freeReplyObject(this->reply_);
    return true;

}
bool RedisMgr::ExistsKey(const std::string &key)
{

    //从连接池获取连接
    this->connect_ = pool_->GetConnection();
    if(this->connect_==nullptr)
    {
        std::cout << "get redis connection failed" << std::endl;
        return false;
    }

    //利用RAII思想，在函数结束时自动释放连接
    Defer defer([this](){pool_->ReturnConnection(this->connect_); connect_=nullptr;});




    reply_ = (redisReply*)redisCommand(connect_,"EXISTS %s",key.c_str());
    if(reply_==NULL||reply_->type!=REDIS_REPLY_INTEGER)
    {
        std::cout<<"[EXISTS  "<<key<<" ] failed"<<std::endl;
        if (reply_)
        {
            freeReplyObject(reply_);
        }
        
        return false;
    }
    std::cout << "Execute command [ EXISTS " << key << " ] success, return value : " << this->reply_->integer << std::endl;
    freeReplyObject(this->reply_);
    return true;
}




RedisMgr::RedisMgr()
{
    auto & configMgr = ConfigMgr::GetInstance();
    std::string host = configMgr["Redis"]["Host"];
    std::string port = configMgr["Redis"]["Port"];
    std::string pwd = configMgr["Redis"]["Passwd"];

    pool_ = std::make_unique<RedisConPool>(6,host.c_str(),stoi(port),pwd.c_str());

}

bool RedisMgr::HDel(const std::string &key, const std::string &hkey)
{
    // 从连接池中获取连接
    this->connect_ = pool_->GetConnection();
    if(this->connect_==nullptr)
    {
        std::cout << "get redis connection failed" << std::endl;
        return false;
    }
    // 利用RAII思想，在函数结束时自动释放连接
    Defer defer([this](){
        pool_->ReturnConnection(this->connect_); 
        connect_=nullptr;
    });

    reply_ = (redisReply*)redisCommand(connect_,"HDEL %s %s",key.c_str(),hkey.c_str());
    if(reply_==NULL||reply_->type!=REDIS_REPLY_INTEGER)
    {
        std::cout<<"[HDEL  "<<key<<" "<<hkey<<" ] failed"<<std::endl;
        if (reply_)
        {
            freeReplyObject(reply_);
        }
        
        return false;
    }
    
    freeReplyObject(reply_);
    return true;
}